eventcontroller, widget: Don't crash if destroyed before the other
authorDebarshi Ray <debarshir@gnome.org>
Sun, 1 Mar 2015 12:28:21 +0000 (13:28 +0100)
committerDebarshi Ray <debarshir@gnome.org>
Mon, 2 Mar 2015 10:53:52 +0000 (11:53 +0100)
There are two scenarios. A widget sub-class owns a GtkEventController
and passes itself to it, or a controller owned by something else is
passed a widget.

In the second case, if the widget is destroyed before the controller,
we will have a crash when destructing the controller because we will
be accessing invalid memory. Adding a weak reference on the widget
addresses that problem.

This leads to a crash in the first case. When the widget is getting
destroyed, it will drop the reference to its own controller. The
controller will skip touching the widget because the weak reference
would have turned it to NULL. However, when the widget sub-class chains
up to GtkWidget it will try to free all the controllers in its list.
Unfortunately, all these controllers have already been destroyed. So
we need to guard against this too.

https://bugzilla.gnome.org/show_bug.cgi?id=745225

gtk/gtkeventcontroller.c
gtk/gtkwidget.c

index 4a77040bdd40ae968b2ffc8ab3cbbf6e151ef805..c20c84e0d3685430d867905c37cc1403c1bdce4d 100644 (file)
@@ -75,6 +75,7 @@ gtk_event_controller_set_property (GObject      *object,
     {
     case PROP_WIDGET:
       priv->widget = g_value_get_object (value);
+      g_object_add_weak_pointer (G_OBJECT (priv->widget), (gpointer *) &priv->widget);
       break;
     case PROP_PROPAGATION_PHASE:
       gtk_event_controller_set_propagation_phase (GTK_EVENT_CONTROLLER (object),
index 11307c6032c3c337cf960ec95972b086fcf3ccf7..7f132df0c0d6bd845af6303b1e5ac67c90da0052 100644 (file)
@@ -17221,6 +17221,8 @@ _gtk_widget_add_controller (GtkWidget           *widget,
     g_signal_connect (widget, "grab-notify",
                       G_CALLBACK (event_controller_grab_notify), data);
 
+  g_object_add_weak_pointer (G_OBJECT (data->controller), (gpointer *) &data->controller);
+
   if (GTK_IS_GESTURE (controller))
     {
       data->sequence_state_changed_id =